﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace XChip_Common
{
   // using HslCommunication.Serial;
 public   class Setting2Help
    {
        /// <summary>
        /// 清理Lib文件夹内的文件
        /// </summary>
        public static void ClearLibFile()
        {
            List<string> files = new List<string>();
            Task.Run(() =>
            {
                FileHelper.GetFiles(Application.StartupPath + "\\Lib", ref files);
                foreach (var file in files)
                {
                    string fileName = Path.GetFileName(file);
                   
                    if (  fileName.Contains("FSys") || fileName.Contains("RxFlash1K") || fileName.Contains("TxFlash1K") || fileName.Contains("ML.dll") || fileName.Contains("MLNative.dll") || fileName.Contains("MWArray.dll") || fileName.Contains("readme.txt")
                        || fileName.Contains("IQ_Register_3D.txt") || fileName.Contains("IQ_Register_Templete.txt") || fileName.Contains("save_exit.txt") || fileName.Contains("reset.txt"))
                    {
                        continue;
                    }
                    File.Delete(file);
                }
            });
        }
       
        /// <summary>
        /// setting 转Bin 
        /// </summary>
        /// <param name="outputfile">输出文件</param>
        /// <param name="fsmList">地址 和文件 集合</param>
        /// <param name="model">大小端</param>
        /// <param name="isRandom">是否随机码</param>
        public static void FlashSetting2Bin(string outputfile, List<FlashSettingModel> fsmList,int model=0,bool isRandom=false) {

            try
            {
                string pSavePath = System.IO.Path.GetDirectoryName(outputfile); //获取文件路径
                string pLocalName = System.IO.Path.GetFileName(outputfile); //获取文件名
                List<FlashSettingModel> fsmTempList = new List<FlashSettingModel>();
                Random rd = new Random();
                for (int i = 0; i < fsmList.Count; i++)
                {
                    FlashSettingModel modelTemp = new FlashSettingModel();
                    modelTemp.fileAddr = fsmList[i].fileAddr;
                    modelTemp.fileLength = fsmList[i].fileLength;
                    modelTemp.fileName = fsmList[i].fileName;
                    modelTemp.fByte = new List<byte>();

                    var addr1 = getUintToString(fsmList[i].fileAddr);
                    //var addr2 = getUintToString(fsmList[i + 1].fileAddr);

                    var flength = getUintToString(fsmList[i].fileLength);


                    string fpathName = string.Empty;
                    if (!fsmList[i].fileName.Contains(pSavePath)) //判断文件路径是否和生成路径一致   兼容以前代码逻辑
                    {
                        fpathName = $"{pSavePath}\\{System.IO.Path.GetFileName(fsmList[i].fileName)}";
                    }
                    else
                    {
                        fpathName = fsmList[i].fileName;
                    }
                    //var fpath = HeaderHelper.FilePathLength(fpathName); //取消读取文件  存在空格也算长度  故取消使用读取文件长度  但是可以作为参考
                    //var fData = File.ReadAllText(fpathName);

                    List<string> tempStrList = FileProcessing(fpathName);
                    //var fList = fData.Replace("\n", "").Replace("\r","").Replace(" ","").Split(',');                   
                    var fList = tempStrList.ToArray();
                    if (i == 0)//首地址
                    {
                        var addrTemp = addr1 - 0x0000;
                        for (int x = 0; x < addrTemp / 4; x++) //填补空缺
                        {
                            byte[] bTemp = new byte[4];
                            bTemp[0] = Convert.ToByte(rd.Next(0, 255));
                            bTemp[1] = Convert.ToByte(0);
                            bTemp[2] = Convert.ToByte(rd.Next(0, 255));
                            bTemp[3] = Convert.ToByte(rd.Next(0, 255));
                            modelTemp.fByte.AddRange(bTemp);
                        }
                        for (int x = 0; x < addrTemp % 4; x++)//地址是基数地址时添加到起始位置
                        {
                            modelTemp.fByte.Add(Convert.ToByte(rd.Next(0, 255)));
                        }
                    }
                    else
                    {
                        if ((i + 1 < fsmList.Count)) //这里确定是用下个地址的
                        {
                            var addr2 = getUintToString(fsmList[i + 1].fileAddr);
                            flength = addr2 - addr1;
                            modelTemp.fileLength = flength.ToString("X4");
                        }
                    }


                    //1.0 读取文件内容存入
                    foreach (var item in fList)
                    {
                        byte[] bTemp = new byte[4];

                        if (!string.IsNullOrEmpty(item))
                        {
                            var tempUint = getUintToString(item);
                            if (model == 0)
                            {
                                bTemp[0] = (byte)(tempUint & 0xff);
                                bTemp[1] = (byte)(tempUint >> 8 & 0xff);
                                bTemp[2] = (byte)(tempUint >> 16 & 0xff);
                                bTemp[3] = (byte)(tempUint >> 24 & 0xff);
                            }
                            else
                            {
                                bTemp[3] = (byte)(tempUint & 0xff);
                                bTemp[2] = (byte)(tempUint >> 8 & 0xff);
                                bTemp[1] = (byte)(tempUint >> 16 & 0xff);
                                bTemp[0] = (byte)(tempUint >> 24 & 0xff);
                            }
                            modelTemp.fByte.AddRange(bTemp);
                        }
                    }
                    UInt32 ftemp = Convert.ToUInt32(modelTemp.fByte.Count());
                    if (isRandom) //不添加随机码  添加0xff
                    {
                        /**  随机码处理方式：
                              1.头文件  随机码 + 加头文件 + 随机码
                              2.除头文件以为 随机码 + 剩余空间 （下一个文件大小的*0.5 递归）
                        **/

                        //计算需要填补的空间
                        var cadd = (flength - ftemp);
                        if (i == 0)
                        {
                            if (cadd > ftemp)
                            {
                                var tempfByte = new List<byte>(modelTemp.fByte);
                                cadd = cadd - ftemp;
                                var rdTemp = rd.Next(0, Convert.ToInt32(cadd.ToString()));
                                while (!(rdTemp % 4 == 0))
                                {
                                    rdTemp = rd.Next(0, Convert.ToInt32(cadd.ToString()));
                                }
                                if (rdTemp > 0)
                                {
                                    for (int p = 0; p < rdTemp / 4; p++)
                                    {
                                        byte[] bTemp = new byte[4];
                                        bTemp[0] = Convert.ToByte(rd.Next(0, 255));
                                        bTemp[1] = Convert.ToByte(0);
                                        bTemp[2] = Convert.ToByte(rd.Next(0, 255));
                                        bTemp[3] = Convert.ToByte(rd.Next(0, 255));
                                        modelTemp.fByte.AddRange(bTemp);
                                    }
                                }

                                cadd = cadd - Convert.ToUInt32(rdTemp.ToString());
                                modelTemp.fByte.AddRange(tempfByte);
                            }
                            else
                            {
                                var headCount = ftemp / 2;
                                while (headCount > cadd)
                                {
                                    headCount = headCount /2;
                                }
                                while (!(headCount % 4 == 0))
                                {
                                    headCount++;
                                }
                                modelTemp.fByte.AddRange(modelTemp.fByte.Take(Convert.ToInt32(headCount.ToString())).ToList());
                                cadd = cadd - Convert.ToUInt32(headCount.ToString());
                            }
                        }
                        else
                        {

                            if ((i + 1) < fsmList.Count)
                            {
                                var nextPath = $"{pSavePath}\\{System.IO.Path.GetFileName(fsmList[i + 1].fileName)}";
                                var fnextpath = HeaderHelper.FilePathLength(nextPath);
                                var headCount = Convert.ToUInt32(fnextpath, 16) ;
                                while (headCount > cadd)
                                {
                                    headCount = headCount / 2;
                                }
                                while (!(headCount % 4 == 0))
                                {
                                    headCount++;
                                }
                                cadd = cadd - Convert.ToUInt32(headCount);
                                //var fDataT = File.ReadAllText($"{pSavePath}\\{System.IO.Path.GetFileName(fsmList[i + 1].fileName)}");
                                //var fListT = fDataT.Replace("\n", "").Replace("\r", "").Replace(" ", "").Split(',');
                                List<string> fDataT = FileProcessing($"{pSavePath}\\{System.IO.Path.GetFileName(fsmList[i + 1].fileName)}");
                                var fListT = fDataT.ToArray();


                                foreach (var item in fListT)
                                {
                                    if (headCount <= 0)
                                    {
                                        continue;
                                    }
                                    byte[] bTemp = new byte[4];
                                    if (!string.IsNullOrEmpty(item))
                                    {
                                        var tempUint = getUintToString(item);
                                        if (model == 0)
                                        {
                                            bTemp[0] = (byte)(tempUint & 0xff);
                                            bTemp[1] = (byte)(tempUint >> 8 & 0xff);
                                            bTemp[2] = (byte)(tempUint >> 16 & 0xff);
                                            bTemp[3] = (byte)(tempUint >> 24 & 0xff);
                                        }
                                        else
                                        {
                                            bTemp[3] = (byte)(tempUint & 0xff);
                                            bTemp[2] = (byte)(tempUint >> 8 & 0xff);
                                            bTemp[1] = (byte)(tempUint >> 16 & 0xff);
                                            bTemp[0] = (byte)(tempUint >> 24 & 0xff);
                                        }
                                        modelTemp.fByte.AddRange(bTemp);
                                        headCount -= 4;

                                    }
                                }
                            }
                            else
                            {
                                var headCount = ftemp / 2;
                                while (headCount > cadd)
                                {
                                    headCount = headCount / 2;
                                }
                                while (!(headCount % 4 == 0))
                                {
                                    headCount++;
                                }
                                modelTemp.fByte.AddRange(modelTemp.fByte.Take(Convert.ToInt32(headCount.ToString())).ToList());
                                cadd = cadd - Convert.ToUInt32(headCount.ToString());
                            }
                        }

                    
                        for (int z = 0; z < cadd / 4; z++)
                        {
                            byte[] bTemp = new byte[4];
                            bTemp[0] = Convert.ToByte(rd.Next(0, 255));
                            bTemp[1] = Convert.ToByte(0);
                            bTemp[2] = Convert.ToByte(rd.Next(0, 255));
                            bTemp[3] = Convert.ToByte(rd.Next(0, 255));
                            modelTemp.fByte.AddRange(bTemp);
                        }
                    }
                    else
                    {
                        //var ftemp = Convert.ToUInt32(fpath, 16);
                        var cadd = (flength - ftemp);
                        for (uint j = 0; j < cadd; j++)
                        {
                            modelTemp.fByte.Add(0xff);
                        }

                    }
                    fsmTempList.Add(modelTemp);
                }

                List<byte> bListByte = new List<byte>();
                foreach (var item in fsmTempList)
                {
                    //检查长度是否到达
                    if (item.fByte.Count() < Convert.ToInt32(item.fileLength, 16))
                    {
                        var bTemp = Convert.ToInt32(item.fileLength, 16) - item.fByte.Count();
                        for (int z = 0; z < bTemp; z++)
                        {
                            item.fByte.Add(Convert.ToByte(rd.Next(0, 255)));
                        }
                    }
                    bListByte.AddRange(item.fByte);

                }
                File.WriteAllBytes(outputfile, bListByte.ToArray());
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }
        /// <summary>
        /// 处理flash文件，去除注释、逗号、0x
        /// </summary>
        /// <param name="fpathName"></param>
        /// <returns></returns>
        public static List<string> FileProcessing(string fpathName)
        {
            #region 处理flash文件，去除注释、逗号、0x
            StreamReader sr = new StreamReader(fpathName);
            string tempStr = string.Empty;
            List<string> tempStrList = new List<string>();
            while ((tempStr = sr.ReadLine()) != null)
            {
                if (tempStr.Contains("//"))
                {
                    var index = tempStr.IndexOf("//");
                    tempStr = tempStr.Remove(index);
                }
                tempStr = tempStr.Trim().Replace(",", "").Replace("，", "").Replace("0x", "");
                List<string> listStr = Regex32ToString(tempStr);
                if(null!= listStr && listStr.Count > 0)
                {
                    tempStr = listStr.First();
                    tempStrList.Add(tempStr);
                }   
            }
            sr.Close();

            #endregion
            return tempStrList;
        }

        private static UInt32 getUintToString(string addr) {
            
            if (addr.Contains("0x"))
            {
                var temp = addr.Replace("0x", "").Trim();
                return Convert.ToUInt32(temp, 16);
            }
            else if (string.IsNullOrEmpty(addr))
            {
                return 0x0;
            }
            else {

                return Convert.ToUInt32(addr.Trim(), 16);
            }
        }

        /// <summary>
        /// header转Flash 或者e2pro
        /// </summary>
        /// <param name="inputfile">输入文件</param>
        /// <param name="outputfile">输出文件</param>
        /// <param name="model">0: EEPROM mode  1: Flash mode</param>
        /// <param name="e2prommode">e2prom mode 开始 addr</param>
        public static void FlashHeader2Flash(string inputfile,string outputfile,int model=1,uint e2prommode=0x0) {
            if (string.IsNullOrEmpty(inputfile))
            {
                return;
            }
            var listFile = ReadTextFileToList(inputfile);
            List<byte> listByte = new List<byte>();
            foreach (var item in listFile)
            {
                if (!string.IsNullOrEmpty(item))
                {
                    string temp = item.Contains("//")? item.Remove(item.IndexOf("//")) :item;//移除注释
                    //if (temp.Contains("//"))
                    //{
                    //    var index = item.IndexOf("//");
                    //    temp = item.Remove(index);
                    //}
                    var listReg = Regex16ToString(temp);
                    if (listReg.Count == 2)
                    {
                        listByte.Add((byte)Convert.ToUInt32(listReg[1], 16));
                    }
                   
                }
                
            }
            if (listByte.Count % 4 != 0)
            {
                int alignment = 4 - (listByte.Count % 4);
                for (int i = 0; i < alignment; i++)
                {
                    listByte.Add(0x00);
                }
            }
            UInt16 crc_check = XchipCrcCheck16(0xFFFF, listByte.ToArray());
            uint crc_Reg = (uint)((0xfffc << 16) + crc_check);
            List<uint> listUint = new List<uint>();
            for (int i = 0; i < listByte.Count/4; i++)
            {
                var hig1 = (Convert.ToUInt32(listByte[i * 4]) << 24);
                var hig2 = (Convert.ToUInt32(listByte[i * 4 + 1]) << 16);
                var low1 = (Convert.ToUInt32(listByte[i * 4 + 2]) << 8);
                var low2 = Convert.ToUInt32(listByte[i * 4 + 3]);
                long temp = hig1 + hig2 + low1 + low2;
                listUint.Add(Convert.ToUInt32(temp));
            }

            if (model == 0)
            {
                //var crc_Reg = (0xfffc << 16) + crc_check;
                listByte.Add((byte)Convert.ToUInt32((crc_Reg >> 24) & 0xff));
                listByte.Add((byte)Convert.ToUInt32((crc_Reg >> 16) & 0xff));
                listByte.Add((byte)Convert.ToUInt32((crc_Reg >> 8) & 0xff));
                listByte.Add((byte)Convert.ToUInt32((crc_Reg ) & 0xff));
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < listByte.Count; i++)
                {
                    sb.Append($"0x{(i+e2prommode).ToString("x4")},0x{listByte[i].ToString("x2")},\n");
                }
                File.WriteAllText(outputfile, sb.ToString());
            }
            else {
                listUint.Add(crc_Reg);
                StringBuilder sb = new StringBuilder();
                foreach (var item in listUint)
                {
                    sb.Append($"0x{item.ToString("x8")},\n");
                }
                File.WriteAllText(outputfile, sb.ToString());
            }
        }


        #region  全局变量
        private static  UInt16 I2C_addr = 0x36; //IIC地址，初始为36
        private static UInt16 I2C_mode = 1;        //IIC模式
        private static UInt16 duxin_mode = 1;      //度信模式
        private static UInt16 ISP_top = 0x50;
        private static int Model;
        private static UInt32 E2promMode;
        private static bool Usage;
        private static bool IsNoKey;
        private static bool I2cLianXie;
        private static bool checkNum = true; //0xfff5 里面的一个开关
        private static UInt16 checkNumTemp = 0;
        /// <summary>
        /// crc 全局变量
        /// </summary>
        static UInt16[] crc16_table ={
                0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
                0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
                0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
                0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
                0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
                0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
                0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
                0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
                0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
                0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
                0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
                0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
                0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
                0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
                0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
                0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
                0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
                0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
                0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
                0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
                0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
                0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
                0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
                0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
                0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
                0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
                0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
                0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
                0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
                0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
                0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
                0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
        };

        public static uint XCHIP_ID = 0x58430128;

        #endregion


        /// <summary>
        /// Setting转Flash 或者e2pro
        /// </summary>
        /// <param name="inputfile">输入文件</param>
        /// <param name="outputfile">输出文件</param>
        /// <param name="model">0: EEPROM mode  1: Flash mode</param>
        /// <param name="e2prommode">e2prom mode 开始 addr</param>
        /// <param name="Usage">0 ：Usage scenarios:FPGA   1：Usage scenarios:CHIP</param>
        /// <param name="isNoKey">0：不忽略 1：忽略关键字</param>
        /// <param name="i2clianxie">0：不i2c连写模式 1：i2c连写模式</param>
        public static void FlashSetting2Flash(string inputfile, string outputfile, int _model=1, uint _e2prommode = 0x0, int _usage = 1, int _isNoKey = 0, int _i2clianxie = 0) {
            if (string.IsNullOrEmpty(inputfile))
            {
                return;
            }
            Model = _model;
            E2promMode = _e2prommode;
            Usage = _usage == 0 ? true : false;
            IsNoKey = _isNoKey == 0 ? false : true;
            I2cLianXie = _i2clianxie == 0 ? false : true;



          I2C_addr = 0x36; //IIC地址，初始为36
          I2C_mode = 1;        //IIC模式
          duxin_mode = 1;      //度信模式
          ISP_top = 0x50;
          checkNum = true; //0xfff5 里面的一个开关
          checkNumTemp = 0;


            var listFile = ReadTextFileToList(inputfile);
            List<ISPReg> listByte = new List<ISPReg>();
            List<uint> bootSet = new List<uint>();//模式不同
            foreach (var item in listFile)
            {
                
                if (!string.IsNullOrEmpty(item))
                {
                    
                    //if (item.Contains("{")|| item.Contains("#region")||item.Contains("}")|| (item.Length>= 2&& item.Substring(0, 2).Contains("//")))
                    //{
                    //    continue;
                    //}
                    if ((item.Length >= 2 && item.Substring(0, 2).Contains("0x")))
                    {
                        var listReg = Regex16ToString(item);
                        if (listReg.Count >= 2)
                        {
                            listByte.Add(new ISPReg() { addr = Convert.ToUInt32(listReg[0], 16), value = Convert.ToUInt32(listReg[1], 16) });
                        }
                    }
                    
                }
            }
            //用来验证文件
            //StringBuilder sb = new StringBuilder();
            //for (int i = 0; i < listByte.Count; i++)
            //{
            //    sb.Append($"0x{listByte[i].addr.ToString("x4")},0x{listByte[i].value.ToString("x2")},\r\n");
            //}
            //File.WriteAllText(outputfile, sb.ToString());

            MakeBootSet(listByte, ref bootSet);
            InsCrcCheck(listByte, ref bootSet);
            WriteBootSet(outputfile, listByte, ref bootSet);
        }

        /// <summary>
        /// 根据文件路劲生成 ISPReg
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static List<ISPReg> RegArrToPath(string path) {
            var listFile = ReadTextFileToList(path);
            List<ISPReg> listByte = new List<ISPReg>();
            foreach (var item in listFile)
            {
                if (!string.IsNullOrEmpty(item))
                {
                    if ((item.Length >= 2 && item.Substring(0, 2).Contains("0x")))
                    {
                        var listReg = Regex16ToString(item);
                        if (listReg.Count >= 2)
                        {
                            listByte.Add(new ISPReg() { addr = Convert.ToUInt32(listReg[0], 16), value = Convert.ToUInt32(listReg[1], 16) });
                        }
                    }

                }
            }
            return listByte;
        }


        public static void MakeBootSet(List<ISPReg> listByte, ref List<uint> bootSet) {
            //1.为头文件进行位置预留
            for (int m = 0; m < 4; m++)
            {
                bootSet.Add(0x00);
            }
            bool lianxieStartMask = false;//连写启动模式
            int i = 0;
            while (i<listByte.Count)
            {                
                if (IsNoKey)
                {
                    i += Mode_ISP(i,listByte,ref bootSet);
                    continue;
                }
                if (lianxieStartMask)//连写模式一旦进入 就不会退出，之后改i2c地址和i2c模式
                {
                    if (listByte[i].addr == 0xfff0 || listByte[i].addr == 0xfff8)
                    {
                        I2C_addr =(UInt16)listByte[i].value;
                        i++;
                    }
                    //修改IIC模式
                    else if ((listByte[i].addr == 0xfff1))
                    {
                        //I2C_mode = regs[i].value;
                        Mode_0xFFF1(i, listByte);
                        //Mode_0xfff1(i);
                        i++;
                    }
                    //度信外部模式下，修改IIC模式
                    else if ((listByte[i].addr == 0xfffe) && (listByte[i - 1].addr == 0xfff8))
                    {
                        Mode_0xFFF1(i, listByte);
                        //mode_0xfff1(i);
                        i++;
                    }
                    else
                    {
                        i +=  Mode_Sensor(i, listByte,ref bootSet);
                    }
                }
                //修改度信模式
                else if (listByte[i].addr == 0xffff)
                {
                    Mode_OxFFFF(i, listByte,ref bootSet);
                    i++;
                }
                //修改IIC地址
                else if (listByte[i].addr == 0xfff0 || listByte[i].addr == 0xfff8)
                {
                    if (I2cLianXie)
                    {
                        lianxieStartMask = true;
                        duxin_mode = 0;
                    }
                    I2C_addr =(UInt16) listByte[i].value;
                    i++;
                }//修改IIC模式
                else if ((listByte[i].addr == 0xfff1))
                {
                    //I2C_mode = regs[i].value;
                    //mode_0xfff1(i);
                    Mode_0xFFF1(i, listByte);
                    i++;
                }//度信外部模式下，修改IIC模式
                else if ((duxin_mode == 0) && (listByte[i].addr == 0xfffe))
                {
                    Mode_0xFFF1(i, listByte);
                    i++;
                }//FFFD Mode
                else if (listByte[i].addr == 0xfffd)
                {
                    bootSet.Add(Convert.ToUInt32((listByte[i].addr << 16) + listByte[i].value));
                    i++;
                }//修改ISP高24位地址
                else if (listByte[i].addr == 0xfffe)
                {
                    Mode_0xFFFE(i, listByte, ref bootSet);
                   
                    //mode_0xfffe(i);
                    i++;
                }//版本需求问题，不再使用此模式
                 //else if (listByte[i].addr == 0xfff5)
                 //{
                 //    //mode_0xfff5(i);
                 //    Mode_0xFFF5(i, listByte, ref bootSet);
                 //    i++;
                 //}
                 //对ISP进行配置时
                else if ((I2C_addr == 0x36) || (I2C_addr == 0x38))
                {
                    i += Mode_ISP(i,listByte,ref bootSet);
                }
                //Sensor模式
                else
                {
                    i += Mode_Sensor(i,listByte,ref bootSet);
                }
            }

        }

        public static void WriteBootSet(string outputfile, List<ISPReg> listByte, ref List<uint> bootSet) {

            bootSet[0] =(XCHIP_ID);
            bootSet[1] =(Convert.ToUInt32( bootSet.Count));
            bootSet[2] =((uint)((0xfff5 << 16) + crc_check(0, 2, listByte, bootSet)));

            if (Model == 0)
            {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < bootSet.Count; i++)
                {
                    sb.Append($"0x{(i*4 + E2promMode).ToString("x4")},0x{(bootSet[i]>>24 &0xff).ToString("x2")},\n");
                    sb.Append($"0x{(i*4 +1+ E2promMode).ToString("x4")},0x{(bootSet[i]>>16 & 0xff).ToString("x2")},\n");
                    sb.Append($"0x{(i*4 +2+ E2promMode).ToString("x4")},0x{(bootSet[i]>>8 &0xff).ToString("x2")},\n");
                    sb.Append($"0x{(i*4 +3+ E2promMode).ToString("x4")},0x{(bootSet[i]&0xff).ToString("x2")},\n");
                }
                File.WriteAllText(outputfile, sb.ToString());
            }
            else
            {
                StringBuilder sb = new StringBuilder();
                foreach (var item in bootSet)
                {
                    sb.Append($"0x{item.ToString("x8")},\n");
                }
                File.WriteAllText(outputfile, sb.ToString());
            }
        }

        public static void InsCrcCheck(List<ISPReg> listByte, ref List<uint> bootSet) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < bootSet.Count; i++)
            {
                sb.Append($"0x{bootSet[i].ToString("x8")},\r\n");
            }
            //File.WriteAllText("C:\\Users\\Administrator\\Desktop\\insCrcCheck22.txt", sb.ToString());


            int count = bootSet.Count;       //由于setCount的值会改变，故使用temp作为计数
            int CRCCHECKNUM = 128;
            //int arry[CRCCHECKNUM * 11]; //用于存放校验值的数组
            List<int> arry = new List<int>();
            int check_num = (count - 4) / (CRCCHECKNUM / 4);    //单次校验数

            //1.从有效数据开始，每CRCCHECKNUM/4为一组，进行crc校验，并将所有校验值按顺序写入数组arry中
            for (int i = 0; i < check_num; i++)
            {
                int a = 4 + (CRCCHECKNUM / 4) * i;
                arry.Add(crc_check(4 + (CRCCHECKNUM / 4) * i, (CRCCHECKNUM / 4),listByte, bootSet));
            }
            //2.将余下不足CRCCHECKNUM/4的数据进行数据补齐并校验插值
            int alignment = (count - 4) % (CRCCHECKNUM / 4);
            if (alignment != 0)
            {
                int bef_end = (check_num) * (CRCCHECKNUM / 4) + 4;
                for (int i = 0; i < (CRCCHECKNUM / 4) - alignment; i++)
                {
                    bootSet.Add(0xfff70000);
                    //WriteReg(0xfff70000);
                }
               
                InsValue(bef_end,(uint)((0xf5f5 << 16) + crc_check(bef_end, (CRCCHECKNUM / 4),listByte,bootSet)),listByte,ref bootSet); //CRC关键字 0xf5f5 
            }
            //3.将arry中的值按顺序插入正确的地址
            for (int i = 0; i < check_num; i++)
            {
                InsValue(4 + (128 / 4 + 1) * (i),(uint)((0xf5f5 << 16) + arry[i]),listByte,ref bootSet); //CRC关键字 0xf5f5  CRC校验128
            }
        }


        public static int Mode_ISP(int count, List<ISPReg> listByte,ref List<uint> bootSet)
        {
            if (IsNoKey)
            {
                bootSet.Add((listByte[count].addr << 16) + listByte[count].value);
                return 1;
            }
            if (ISP_top == 0x50 && listByte[count].addr == 0x4d)
            {
                if ((listByte[count].value & 0x01) == 0x01)
                {
                    listByte[count].value &= 0xFE;
                  
                }
                bootSet.Add((listByte[count].addr << 16) + listByte[count].value);
                return 1;
            }
            else if (ISP_top == 0xff)
            {
                if (Usage)
                {
                    bootSet.Add((listByte[count].addr << 16) + listByte[count].value);
                }
                return 1;
            }
            else {
                bootSet.Add((listByte[count].addr << 16) + listByte[count].value);
                return 1;
            }
            //return 0;
        }

        public static void Mode_OxFFFF(int count, List<ISPReg> listByte, ref List<uint> bootSet) {
            if (listByte[count].value == 0xfef1)
            {
                duxin_mode = 1;
            }
            else if (listByte[count].value == 0xfef0)
            {
                duxin_mode = 0;
            }
            else {
                //var temp = (0xffff << 16) + (listByte[count].value);
                bootSet.Add((uint)((0xffff << 16) + (listByte[count].value)));
            }
        }
        public static void Mode_0xFFF1(int count, List<ISPReg> listByte) {
            if ((listByte[count].value == 0) || (listByte[count].value == 1))
            {
                I2C_mode = 0;
            }
            else if (listByte[count].value == 3)
            {
                I2C_mode = 1;
            }
            else if (listByte[count].value == 4)
            {
                I2C_mode = 2;
            }
        }

        public static void Mode_0xFFF5(int count, List<ISPReg> listByte, ref List<uint> bootSet) {
            if (checkNum)
            {
                bootSet.Add(Convert.ToUInt32((0xfff5 << 16) + crc_check(4,bootSet.Count,listByte,bootSet)));
                checkNumTemp =Convert.ToUInt16(bootSet.Count);
            }
            else {
                bootSet.Add(Convert.ToUInt32((0xfff5 << 16) + crc_check(checkNumTemp,(bootSet.Count - checkNumTemp),listByte, bootSet)));
                checkNumTemp = Convert.ToUInt16(bootSet.Count);
            }
        }

        public static void Mode_0xFFFE(int count, List<ISPReg> listByte, ref List<uint> bootSet) {
            if (duxin_mode == 0)
            {
                I2C_mode = (UInt16)listByte[count].value;
            }
            else {
                ISP_top = (UInt16)listByte[count].value;
                if (ISP_top == 0xff)
                {
                    if (Usage)
                    {
                        bootSet.Add(Convert.ToUInt32((listByte[count].addr << 16) + listByte[count].value));
                    }
                }
                else {
                    bootSet.Add(Convert.ToUInt32((listByte[count].addr << 16) + listByte[count].value));
                }
            }
        }
        public static void InsValue(int addr, uint value, List<ISPReg> listByte, ref List<uint> bootSet) {
            if (addr<0) return;
            for (int i = bootSet.Count ; i >= addr; i--)
            {
                if ((i + 1) > bootSet.Count)
                {
                    bootSet.Add(bootSet[i-1]);
                }
                else {
                    bootSet[i + 1] = bootSet[i];
                }
            }
            bootSet[addr] = value;
        }

        public static int Mode_Sensor(int count, List<ISPReg> listByte, ref List<uint> bootSet)
        {
            int sensor_nums = 0;
            
            bootSet.Add((uint)((0xfff6 << 16) + (I2C_addr << 8) + I2C_mode));
            uint sensor_make = Convert.ToUInt32(bootSet.Count());	//缓存SensorSetting地址
            bootSet.Add(0x0);
            if (I2cLianXie)
            {
                while ((count + sensor_nums < listByte.Count)&&(listByte[sensor_nums + count].addr != 0xfff8) &&
                       (listByte[sensor_nums + count].addr != 0xfff0) &&
                       (listByte[sensor_nums + count].addr != 0xfff1) )
                {
                    sensor_nums++;
                }
            }
            else
            {
                while ((count + sensor_nums < listByte.Count)&&(listByte[sensor_nums + count].addr != 0xfffe) &&
                       (listByte[sensor_nums + count].addr != 0xfffd) &&
                       (listByte[sensor_nums + count].addr != 0xfff8) &&
                       (listByte[sensor_nums + count].addr != 0xfff0) &&
                       (listByte[sensor_nums + count].addr != 0xfff1) )
                {
                    sensor_nums++;
                }
            }
            if (I2C_mode == 0)
            {
                for (int i = 0; i < sensor_nums / 2; i++)
                {
                    bootSet.Add(Convert.ToUInt32((listByte[count].addr << 24) +
                    (listByte[count].value << 16) +
                    (listByte[count + 1].addr << 8) +
                    (listByte[count + 1].value)));
                    count += 2;
                }
                if (sensor_nums % 2 != 0)
                {
                    bootSet.Add(Convert.ToUInt32((listByte[count].addr << 24) +
                    (listByte[count].value << 16) +
                    (listByte[count].addr << 8) +
                    (listByte[count].value)));
                }
            }
            else
            {
                for (int i = 0; i < sensor_nums; i++)
                {
                    bootSet.Add(Convert.ToUInt32((listByte[count].addr << 16) + listByte[count].value));
                    count++;
                }
            }
            bootSet[Convert.ToInt32(sensor_make)] = (uint)((0xfff7 << 16) + sensor_nums);
            return sensor_nums;
        }

      

        public static void contiuous_mode(int start, int num, List<ISPReg> listByte, ref List<uint> bootSet) {
            int i= 0;

            bootSet.Add(Convert.ToUInt32((0xfff8 << 16) + num));
            bootSet.Add(Convert.ToUInt32((0xfff9 << 16) + listByte[start].addr));

            for ( i = 0; i < num/4; i++)
            {
                bootSet.Add(Convert.ToUInt32(listByte[start + i * 4 + 0].value << 24) +
                    Convert.ToUInt32(listByte[start + i * 4 + 1].value << 16)+
                    Convert.ToUInt32(listByte[start + i * 4 + 2].value << 8)+
                    Convert.ToUInt32(listByte[start + i * 4 + 3].value));
            }
            if ((num%4)!=0)
            {
                uint temp = 0;
                for ( i = 0; i < (num % 4); i++)
                {
                    temp += (listByte[start + (num / 4) * 4 + i].value << (24 - i * 8));
                }
                bootSet.Add(temp);
            }
        }
        /// <summary>
        /// 计算crc
        /// </summary>
        /// <param name="star"></param>
        /// <param name="lengths"></param>
        /// <param name="listByte"></param>
        /// <param name="bootSet"></param>
        /// <returns></returns>
        private static int crc_check(int star, int lengths,  List<ISPReg> listByte,  List<uint> bootSet)
        {
            if (lengths > 32)
            {
                return 0;
            }
            List<byte> checkList = new List<byte>();
            for (int i = 0; i < lengths; i++)
            {
                checkList.Add((byte)Convert.ToUInt16((bootSet[star + i] >> 24) & 0xff));
                checkList.Add((byte)Convert.ToUInt16((bootSet[star + i] >> 16) & 0xff));
                checkList.Add((byte)Convert.ToUInt16((bootSet[star + i] >> 8) & 0xff));
                checkList.Add((byte)Convert.ToUInt16((bootSet[star + i] ) & 0xff));
            }
          return  XchipCrcCheck16(0xFFFF, checkList.ToArray());
        }

       
       

        public static UInt16 XchipCrcCheck16(UInt16 Input, byte[] data) {
            UInt16 crc_reg = Input;
            for (int i = 0; i < data.Count(); i++)
            {
                var tempCount = (crc_reg ^ data[i]) & 0xff;
                crc_reg = Convert.ToUInt16( (crc_reg >> 8) ^ crc16_table[tempCount]);
            }
            return Convert.ToUInt16(crc_reg & 0xFFFF);
        }
        public static List<string> Regex16ToString(string reg)
        {
            var strlist = new List<string>();
            Regex ConnoteA = new Regex("(0x)[a-fA-F0-9]{1,4}");
            foreach (var item in ConnoteA.Matches(reg))
            {
                strlist.Add(item.ToString().Replace("0x", "").Replace(" ","").ToLower());
            }
            return strlist;
        }
        /// <summary>
        /// 匹配32位int
        /// </summary>
        /// <param name="reg"></param>
        /// <returns></returns>
        public static List<string> Regex32ToString(string reg)
        {
            var strlist = new List<string>();
            Regex ConnoteA = new Regex("[a-fA-F0-9]{8}");
            foreach (var item in ConnoteA.Matches(reg))
            {
                strlist.Add(item.ToString());
            }
            return strlist;
        }

        //读取文本文件转换为List 
        public static List<string> ReadTextFileToList(string fileName)
        {
            List<string> list = new List<string>();
            
            FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            
            StreamReader sr = new StreamReader(fs);
            //使用StreamReader类来读取文件 
            sr.BaseStream.Seek(0, SeekOrigin.Begin);
            // 从数据流中读取每一行，直到文件的最后一行
            string tmp = sr.ReadLine();
            while (tmp != null)
            {
                list.Add(tmp);
                tmp = sr.ReadLine();
            }
            //关闭此StreamReader对象 
            sr.Close();
            fs.Close();
            return list;
        }
        //将List转换为TXT文件
        public void WriteListToTextFile(List<string> list, string txtFile)
        {
            //创建一个文件流，用以写入或者创建一个StreamWriter 
            FileStream fs = new FileStream(txtFile, FileMode.OpenOrCreate, FileAccess.Write);
            StreamWriter sw = new StreamWriter(fs);
            sw.Flush();
            // 使用StreamWriter来往文件中写入内容 
            sw.BaseStream.Seek(0, SeekOrigin.Begin);
            for (int i = 0; i < list.Count; i++) sw.WriteLine(list[i]);
            //关闭此文件t 
            sw.Flush();
            sw.Close();
            fs.Close();
        }

        /// <summary>
        /// 当前这个根据补丁的userkey 进行同步更改  
        /// </summary>
        static int UserKey_XOR = 2;
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static List<string> KeyEntrypt(uint[] inputs)
        {
            ushort[] Entrypt_Key = new ushort[8];
            List<string> strlist = new List<string>();
            for (int i = 0; i < 8; i++)
            {
                var str = (ushort)(inputs[i] ^ crc16_table[i * 8 + UserKey_XOR]); 
                var result = (ushort)((str & 0xFF) << 8) | (str >> 8);
                result = (ushort)Math.Min(result, ushort.MaxValue);  
                var resultAsUShort = (ushort)result; 
                Entrypt_Key[i] = resultAsUShort; 
                strlist.Add(Entrypt_Key[i].ToString("X4"));
            }
            return strlist;
        }


    }

    public class FlashSettingModel {
      public string fileAddr { get; set; }
      public string fileName { get; set; }
      public string fileLength { get; set; }
      public List<byte> fByte { get; set; }
    }

    public class ISPReg {
        public UInt32 addr;
        public UInt32 value;
        public string note;
    }

}
